package com.uinnova.product.eam.service.cj.service.impl;

import com.binary.core.lang.StringUtils;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.uinnova.product.eam.model.cj.domain.ChapterResource;
import com.uinnova.product.eam.model.cj.domain.PlanTemplateChapter;
import com.uinnova.product.eam.model.cj.domain.PlanTemplateChapterData;
import com.uinnova.product.eam.model.cj.domain.ReferencesInfo;
import com.uinnova.product.eam.model.cj.enums.TableContentTypeEnum;
import com.uinnova.product.eam.model.cj.vo.*;
import com.uinnova.product.eam.model.constants.Constants;
import com.uinnova.product.eam.service.cj.dao.ChapterResourceDao;
import com.uinnova.product.eam.service.cj.dao.PlanTemplateChapterDao;
import com.uinnova.product.eam.service.cj.dao.PlanTemplateChapterDataDao;
import com.uinnova.product.eam.service.cj.service.PlanTemplateChapterService;
import com.uinnova.product.eam.service.exception.BusinessException;
import com.uinnova.product.eam.service.utils.XssCleanerUtil;
import com.uino.bean.permission.base.SysUser;
import com.uino.dao.util.ESUtil;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.xss.core.XssType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: Lc
 * @create: 2022-01-05 16:59
 */
@Slf4j
@Service
public class PlanTemplateChapterServiceImpl implements PlanTemplateChapterService {

    @Resource
    private PlanTemplateChapterDao planTemplateChapterDao;

    @Resource
    private ChapterResourceDao chapterResourceDao;

    @Resource
    private PlanTemplateChapterDataDao planTemplateChapterDataDao;

    @Value("${http.resource.space}")
    private String httpPath;

    @Override
    public Long addPlanTemplateChapter(PlanTemplateChapterVo planTemplateChapterVo, SysUser user) {
        checkPlanTemplateChapter(planTemplateChapterVo);
        PlanTemplateChapter planTemplateChapter = planTemplateChapterVo.getPlanTemplateChapter();
        planTemplateChapter.setBusinessId(ESUtil.getUUID());
        planTemplateChapter.setStatus(1);
        // 封装排序规则
        if (planTemplateChapter.getSortNum() == null) {
            planTemplateChapter.setSortNum(handleSortNum(planTemplateChapterVo));
        }
        // 封装操作人和操作时间
        handleUserAndTime(planTemplateChapter, user);
        // 引用按钮可操作
        if (planTemplateChapter.getIntroduceButton() == null) {
            planTemplateChapter.setIntroduceButton(1);
        }
        if (!StringUtils.isBlank(planTemplateChapter.getChapterDesc())) {
            XssCleanerUtil xssCleaner = new XssCleanerUtil();
            String cleanStr = xssCleaner.clean("", planTemplateChapter.getChapterDesc(), XssType.JACKSON);
            planTemplateChapter.setChapterDesc(cleanStr);
        }
        Long result = planTemplateChapterDao.saveOrUpdate(planTemplateChapter);
        // 添加模板数据
        List<PlanTemplateChapterData> chapterDataList = planTemplateChapterVo.getChapterDataList();
        // 模板中的表格信息修改了列宽相关配置，需要调整更新时间，其他场景不变
        transModifyTime(chapterDataList);
        if (!CollectionUtils.isEmpty(chapterDataList)) {
            // 验证章节数据
            chapterDataList.forEach(chapterData -> {
                checkChapterData(chapterData);
            });

            for(int i = 0; i < chapterDataList.size(); i++) {
                PlanTemplateChapterData chapterData = chapterDataList.get(i);
                // 校验表格属性名称重复
                checkTableNameAttrEqual(chapterData);
                chapterData.setConfigOrder(i);
                chapterData.setPlanTemplateId(planTemplateChapter.getPlanTemplateId());
                chapterData.setTemplateChapterId(result);
            }
            // 先操作删除方案章节下的模块
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            queryBuilder.must(QueryBuilders.termQuery("planTemplateId", planTemplateChapter.getPlanTemplateId()));
            queryBuilder.must(QueryBuilders.termQuery("templateChapterId", planTemplateChapter.getId()));
            planTemplateChapterDataDao.deleteByQuery(queryBuilder, true);
            // 批量新增内容块
            planTemplateChapterDataDao.saveOrUpdateBatchNoModifyTime(chapterDataList);
        } else {
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            queryBuilder.must(QueryBuilders.termQuery("planTemplateId", planTemplateChapter.getPlanTemplateId()));
            queryBuilder.must(QueryBuilders.termQuery("templateChapterId", result));
            planTemplateChapterDataDao.deleteByQuery(queryBuilder, true);
        }
        return result;
    }
    /**
     * 处理表格列宽修改时间
     * 当表格列宽相关配置发生变化时，更新修改时间
     *
     * @param chapterDataList 章节数据列表
     */
    private void transModifyTime(List<PlanTemplateChapterData> chapterDataList) {
        if (CollectionUtils.isEmpty(chapterDataList)) {
            log.info("章节数据列表为空，不处理表格列宽修改时间");
            return;
        }

        // 筛选出表格类型的章节数据ID
        List<Long> tableChapterDataIds = chapterDataList.stream()
                .filter(data -> data != null && data.getId() != null && Integer.valueOf(2).equals(data.getType()))
                .map(PlanTemplateChapterData::getId)
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(tableChapterDataIds)) {
            log.info("表格类型的章节数据ID为空，不处理表格列宽修改时间");
            return;
        }

        // 查询数据库数据
        List<PlanTemplateChapterData> dbChapterDataList = planTemplateChapterDataDao.getListByQuery(
                QueryBuilders.termsQuery("id", tableChapterDataIds));

        if (CollectionUtils.isEmpty(dbChapterDataList)) {
            log.info("数据库表格章节数据列表为空，不处理表格列宽修改时间");
            return;
        }

        // 创建数据库数据的映射，方便快速查找
        Map<Long, PlanTemplateChapterData> dbChapterDataMap = dbChapterDataList.stream()
                .collect(Collectors.toMap(
                        PlanTemplateChapterData::getId,
                        Function.identity(),
                        (k1, k2) -> k1
                ));

        // 当前时间戳
        long nowTime = BinaryUtils.getNumberDateTime();

        // 处理每个表格类型的章节数据
        for (PlanTemplateChapterData templateChapterData : chapterDataList) {
            // 跳过非表格类型或ID为空的数据
            if (templateChapterData == null || templateChapterData.getId() == null ||
                    !Integer.valueOf(2).equals(templateChapterData.getType())) {
                continue;
            }

            // 获取数据库中对应的数据
            PlanTemplateChapterData dbData = dbChapterDataMap.get(templateChapterData.getId());
            if (dbData == null) {
                continue;
            }

            // 修改时间先回退至数据库内容
            templateChapterData.setModifyTime(dbData.getModifyTime());

            // 根据表格类型检查列宽是否发生变化
            Integer dataTableForm = templateChapterData.getDataTableForm();
            if (dataTableForm == null) {
                continue;
            }

            boolean hasColumnWidthChanges = false;

            switch (dataTableForm) {
                case 1: // 横向表格
                    hasColumnWidthChanges = checkHorizontalTableColumnWidthChanges(templateChapterData, dbData);
                    break;

                case 2: // 纵向表格
                    hasColumnWidthChanges = checkFirstColumnWidthChanges(templateChapterData, dbData);
                    break;

                case 3: // 矩阵表格
                    hasColumnWidthChanges = checkMatrixTableColumnWidthChanges(templateChapterData, dbData);
                    break;

                default:
                    // 未知表格类型，不处理
                    continue;
            }

            // 如果有列宽相关的修改，更新修改时间
            if (hasColumnWidthChanges) {
                log.info("模块ID={}的{}列宽发生变化，更新修改时间为{}",
                        templateChapterData.getId(),
                        getTableTypeName(dataTableForm),
                        nowTime);
                templateChapterData.setModifyTime(nowTime);
            }
        }
    }

    /**
     * 检查横向表格列宽是否发生变化
     *
     * @param templateData 当前数据
     * @param dbData 数据库数据
     * @return 如果列宽发生变化返回true，否则返回false
     */
    private boolean checkHorizontalTableColumnWidthChanges(PlanTemplateChapterData templateData, PlanTemplateChapterData dbData) {
        List<RowTableContentVo> dataTableContent = templateData.getDataTableContent();
        List<RowTableContentVo> dbDataTableContent = dbData.getDataTableContent();

        // 如果列表为空，不需要比较
        if (CollectionUtils.isEmpty(dataTableContent) || CollectionUtils.isEmpty(dbDataTableContent)) {
            return false;
        }

        // 创建数据库中列的Map，以name和classId为复合键
        Map<String, RowTableContentVo> dbContentMap = dbDataTableContent.stream()
                .collect(Collectors.toMap(
                        e -> getContentKey(e),
                        Function.identity(),
                        (existing, replacement) -> existing
                ));

        // 检查每一列的列宽是否发生变化
        for (RowTableContentVo content : dataTableContent) {
            String key = getContentKey(content);
            String name = content.getName();

            // 如果当前列在数据库中不存在，则是新增列，不需要更新修改时间
            if (!dbContentMap.containsKey(key)) {
                return false;
            }

            RowTableContentVo dbContent = dbContentMap.get(key);

            // 检查columnWidth是否发生变化
            Integer columnWidth = content.getColumnWidth();
            Integer dbColumnWidth = dbContent.getColumnWidth();
            if (isColumnWidthChanged(columnWidth, dbColumnWidth)) {
                log.info("横向表格列宽变化: 列名={}, columnWidth由{}变为{}",
                        name, dbColumnWidth, columnWidth);
                return true;
            }

            // 检查columnWidthValue是否发生变化
            Integer columnWidthValue = content.getColumnWidthValue();
            Integer dbColumnWidthValue = dbContent.getColumnWidthValue();
            if (isColumnWidthChanged(columnWidthValue, dbColumnWidthValue)) {
                log.info("横向表格列宽值变化: 列名={}, columnWidthValue由{}变为{}",
                        name, dbColumnWidthValue, columnWidthValue);
                return true;
            }
        }

        return false;
    }

    /**
     * 检查首列宽度是否发生变化
     *
     * @param templateData 当前数据
     * @param dbData 数据库数据
     * @return 如果首列宽度发生变化返回true，否则返回false
     */
    private boolean checkFirstColumnWidthChanges(PlanTemplateChapterData templateData, PlanTemplateChapterData dbData) {
        Integer firstColumnWidth = templateData.getFirstColumnWidth();
        Integer dbFirstColumnWidth = dbData.getFirstColumnWidth();

        // 检查firstColumnWidth是否发生变化
        if (isColumnWidthChanged(firstColumnWidth, dbFirstColumnWidth)) {
            String tableType = getTableTypeName(templateData.getDataTableForm());
            log.info("{}首列宽度变化: firstColumnWidth由{}变为{}",
                    tableType, dbFirstColumnWidth, firstColumnWidth);
            return true;
        }

        // 检查firstColumnWidthValue是否发生变化
        Integer firstColumnWidthValue = templateData.getFirstColumnWidthValue();
        Integer dbFirstColumnWidthValue = dbData.getFirstColumnWidthValue();
        if (isColumnWidthChanged(firstColumnWidthValue, dbFirstColumnWidthValue)) {
            String tableType = getTableTypeName(templateData.getDataTableForm());
            log.info("{}首列宽度值变化: firstColumnWidthValue由{}变为{}",
                    tableType, dbFirstColumnWidthValue, firstColumnWidthValue);
            return true;
        }

        return false;
    }

    /**
     * 获取表格类型名称
     *
     * @param dataTableForm 表格形式
     * @return 表格类型名称
     */
    private String getTableTypeName(Integer dataTableForm) {
        if (dataTableForm == null) {
            return "未知表格";
        }

        switch (dataTableForm) {
            case 1:
                return "横向表格";
            case 2:
                return "纵向表格";
            case 3:
                return "矩阵表格";
            default:
                return "未知表格(" + dataTableForm + ")";
        }
    }

    /**
     * 检查矩阵表格列宽是否发生变化
     *
     * @param templateData 当前数据
     * @param dbData 数据库数据
     * @return 如果列宽发生变化返回true，否则返回false
     */
    private boolean checkMatrixTableColumnWidthChanges(PlanTemplateChapterData templateData, PlanTemplateChapterData dbData) {
        // 首先检查首列宽度
        if (checkFirstColumnWidthChanges(templateData, dbData)) {
            return true;
        }

        // 然后检查矩阵行的列宽
        List<RowTableContentVo> matrixRow = templateData.getMatrixRow();
        List<RowTableContentVo> dbMatrixRow = dbData.getMatrixRow();

        if (CollectionUtils.isEmpty(matrixRow) || CollectionUtils.isEmpty(dbMatrixRow)) {
            return false;
        }

        // 创建数据库中行的Map，以name为键
        Map<String, RowTableContentVo> dbRowMap = dbMatrixRow.stream()
                .collect(Collectors.toMap(
                        RowTableContentVo::getName,
                        Function.identity(),
                        (existing, replacement) -> existing
                ));

        // 检查每一行的列宽是否发生变化
        for (RowTableContentVo row : matrixRow) {
            String name = row.getName();

            // 如果当前行在数据库中不存在，则是新增行，不需要更新修改时间
            if (!dbRowMap.containsKey(name)) {
                return false;
            }

            RowTableContentVo dbRow = dbRowMap.get(name);

            // 检查columnWidth是否发生变化
            Integer columnWidth = row.getColumnWidth();
            Integer dbColumnWidth = dbRow.getColumnWidth();
            if (isColumnWidthChanged(columnWidth, dbColumnWidth)) {
                log.info("矩阵表格行列宽变化: 行名={}, columnWidth由{}变为{}",
                        name, dbColumnWidth, columnWidth);
                return true;
            }

            // 检查columnWidthValue是否发生变化
            Integer columnWidthValue = row.getColumnWidthValue();
            Integer dbColumnWidthValue = dbRow.getColumnWidthValue();
            if (isColumnWidthChanged(columnWidthValue, dbColumnWidthValue)) {
                log.info("矩阵表格行列宽值变化: 行名={}, columnWidthValue由{}变为{}",
                        name, dbColumnWidthValue, columnWidthValue);
                return true;
            }
        }

        return false;
    }

    /**
     * 获取内容的唯一键
     *
     * @param content 行表格内容
     * @return 唯一键
     */
    private String getContentKey(RowTableContentVo content) {
        return content.getName() + "-" + (BinaryUtils.isEmpty(content.getClassId()) ? "0" : content.getClassId());
    }

    /**
     * 检查列宽是否发生变化
     *
     * @param newWidth 新宽度
     * @param oldWidth 旧宽度
     * @return 如果宽度发生变化返回true，否则返回false
     */
    private boolean isColumnWidthChanged(Integer newWidth, Integer oldWidth) {
        // 如果两者都为null，则认为没有变化
        if (newWidth == null && oldWidth == null) {
            return false;
        }

        // 如果只有一个为null，则认为有变化
        if (newWidth == null || oldWidth == null) {
            return true;
        }

        // 比较两个值是否相等
        return !newWidth.equals(oldWidth);
    }

    /**
     *  校验表格属性名称重复
     * @param chapterData
     */
    private void checkTableNameAttrEqual(PlanTemplateChapterData chapterData) {
        if (!Objects.equals(chapterData.getType(), 2)) {
            // 非表格类型
            return;
        }
        if (Objects.equals(chapterData.getDataTableForm(),1) || Objects.equals(chapterData.getDataTableForm(),2)) {
            List<RowTableContentVo> dataTableContent = chapterData.getDataTableContent();
            Set<String> contentSize = dataTableContent.stream().map(content -> content.getName()).collect(Collectors.toSet());
            if (!Objects.equals(dataTableContent.size(), contentSize.size())) {
                throw new BusinessException("表格属性名称不能重复!");
            }
        } else {
            List<RowTableContentVo> matrixRowList = chapterData.getMatrixRow();
            List<RowTableContentVo> MatrixColList = chapterData.getMatrixCol();
            Set<String> rowContentSize = matrixRowList.stream().map(content -> content.getName()).collect(Collectors.toSet());
            if (!Objects.equals(matrixRowList.size(), rowContentSize.size())) {
                throw new BusinessException("矩阵表格行配置属性名称不能重复!");
            }
            Set<String> colContentSize = MatrixColList.stream().map(content -> content.getName()).collect(Collectors.toSet());
            if (!Objects.equals(MatrixColList.size(), colContentSize.size())) {
                throw new BusinessException("矩阵表格列配置属性名称不能重复!");
            }
        }
    }


    @Override
    public List<PlanTemplateChapterTreeVo> findPlanTemplateChapterList(PlanTemplateChapter templateChapter) {
        if (templateChapter == null) {
            throw new BusinessException("章节参数不能为空!");
        }
        Long planTemplateId = templateChapter.getPlanTemplateId();
        if (planTemplateId == null) {
            throw new BusinessException("方案模板主键不能为空");
        }
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("parentId", 0));
        queryBuilder.must(QueryBuilders.termQuery("planTemplateId", planTemplateId));
        queryBuilder.must(QueryBuilders.termQuery("status", 1));
        long count = planTemplateChapterDao.countByCondition(queryBuilder);
        List<PlanTemplateChapterTreeVo> treeVoList = new ArrayList<>();
        if (count > 0) {
            Page<PlanTemplateChapter> chapterPate = planTemplateChapterDao.getSortListByQuery(1, (int) count, queryBuilder, "sortNum", true);
            List<PlanTemplateChapter> data = chapterPate.getData();
            if (!CollectionUtils.isEmpty(data)) {
                for(int i = 0; i < data.size(); i++) {
                    PlanTemplateChapterTreeVo treeVo = new PlanTemplateChapterTreeVo();
                    BeanUtils.copyProperties(data.get(i), treeVo);
                    treeVo.setSerialNum(String.valueOf(i + 1));
                    treeVo.setFullName(String.valueOf(i + 1) + " "+ treeVo.getChapterName());
                    treeVo.setRequired(Objects.equals(data.get(i).getRequired(), "1"));
                    treeVoList.add(treeVo);

                    BoolQueryBuilder query = QueryBuilders.boolQuery();
                    query.must(QueryBuilders.termQuery("parentId", data.get(i).getId()));
                    query.must(QueryBuilders.termQuery("planTemplateId", planTemplateId));
                    query.must(QueryBuilders.termQuery("status", 1));
                    long childCount = planTemplateChapterDao.countByCondition(query);
                    if (childCount > 0) {
                        Page<PlanTemplateChapter> childChapterPage = planTemplateChapterDao.getSortListByQuery(1, (int) childCount, query, "sortNum", true);
                        List<PlanTemplateChapter> childData = childChapterPage.getData();
                        if (!CollectionUtils.isEmpty(childData)) {
                            List<PlanTemplateChapterTreeVo> childTreeList = new ArrayList<>();
                            for (int j = 0; j < childData.size(); j ++) {
                                PlanTemplateChapterTreeVo childTree = new PlanTemplateChapterTreeVo();
                                BeanUtils.copyProperties(childData.get(j), childTree);
                                StringBuilder sb = new StringBuilder();
                                sb.append(i + 1).append(".").append(j + 1);
                                childTree.setSerialNum(sb.toString());
                                childTree.setFullName(sb.toString() + " " + childTree.getChapterName());
                                childTree.setRequired(Objects.equals(childData.get(j).getRequired(), "1"));
                                childTreeList.add(childTree);
                                treeVo.setChild(childTreeList);
                            }
                            if (!CollectionUtils.isEmpty(childTreeList)) {
                                getChildChapter(childTreeList, planTemplateId);
                            }
                        }
                    }
                }
            }
        } else {
            PlanTemplateChapterVo planTemplateChapterVo = new PlanTemplateChapterVo();
            planTemplateChapterVo.setType(Constants.TEMPLATE_CHAPTER_ADD_TYPE);
            PlanTemplateChapter planTemplateChapter = new PlanTemplateChapter();
            planTemplateChapter.setSortNum(Constants.TEMPLATE_CHAPTER_SORT_NUM);
            planTemplateChapter.setStatus(Constants.TEMPLATE_CHAPTER_STATUS);
            planTemplateChapter.setPlanTemplateId(planTemplateId);
            planTemplateChapter.setChapterName(Constants.TEMPLATE_CHAPTER_NAME);
            planTemplateChapter.setRequired(Constants.TEMPLATE_CHAPTER_REQUIRED);
            planTemplateChapter.setUserAddContent(Constants.USER_ADD_CONTENT);
            planTemplateChapter.setParentId(Constants.TEMPLATE_CHAPTER_PARENT_ID);
            planTemplateChapter.setLevel(Constants.TEMPLATE_CHAPTER_LEVEL);
            planTemplateChapter.setBusinessId(ESUtil.getUUID());
            planTemplateChapterVo.setPlanTemplateChapter(planTemplateChapter);
            Long id = this.addPlanTemplateChapter(planTemplateChapterVo, SysUtil.getCurrentUserInfo());
            planTemplateChapter.setId(id);
            PlanTemplateChapterTreeVo treeVo = new PlanTemplateChapterTreeVo();
            BeanUtils.copyProperties(planTemplateChapter, treeVo);
            treeVo.setSerialNum(Constants.TEMPLATE_SERIAL_NUM);
            treeVo.setFullName(treeVo.getSerialNum() + " " + treeVo.getChapterName());
            treeVo.setRequired(Objects.equals(planTemplateChapter.getRequired(), "1"));
            treeVoList.add(treeVo);
        }
        return treeVoList;
    }

    @Override
    public PlanTemplateChapterDataVo getPlanTemplateChapter(Long id) {
        if (id == null) {
            throw new BusinessException("主键不能为空!");
        }
        PlanTemplateChapter chapter = planTemplateChapterDao.getById(id);
        PlanTemplateChapterDataVo chapterDataVo = new PlanTemplateChapterDataVo();
        if (chapter != null) {
            if (BinaryUtils.isEmpty(chapter.getReferencesInfo())) {
                chapter.setReferencesInfo(new ReferencesInfo());
            }
            chapterDataVo.setChapter(chapter);

            Long planTemplateId = chapter.getPlanTemplateId();
            ChapterResource chapterResource = new ChapterResource();
            chapterResource.setTemplateId(planTemplateId);
            chapterResource.setChapterId(id);
            List<SortBuilder<?>> sorts = new ArrayList<>();
            FieldSortBuilder modifyTimeSortBuilder = SortBuilders.fieldSort("modifyTime").order(SortOrder.ASC);
            sorts.add(modifyTimeSortBuilder);
            List<ChapterResource> chapterResourceList = chapterResourceDao.getSortListByCdt(chapterResource, sorts);
            if (!CollectionUtils.isEmpty(chapterResourceList)) {
                for (ChapterResource resource : chapterResourceList) {
                    ipStringReplacement(resource);
                }
                chapterDataVo.setChapterResource(chapterResourceList);
            }else{
                chapterDataVo.setChapterResource(new ArrayList<>());
            }

            BoolQueryBuilder builder = QueryBuilders.boolQuery();
            builder.must(QueryBuilders.termQuery("planTemplateId", planTemplateId));
            builder.must(QueryBuilders.termQuery("templateChapterId", id));
            long count = planTemplateChapterDataDao.countByCondition(builder);
            if (count > 0) {
                Page<PlanTemplateChapterData> dataPage = planTemplateChapterDataDao.getSortListByQuery(1, (int) count, builder, "configOrder", true);
                if (!CollectionUtils.isEmpty(dataPage.getData())) {
                    for (PlanTemplateChapterData chapterData: dataPage.getData()) {
                        if (Objects.equals(chapterData.getDataTableForm(), 1) || Objects.equals(chapterData.getDataTableForm(), 2)) {
                            chapterData.setMatrixConfig(0);
                            chapterData.setMatrixRow(new ArrayList<>());
                            chapterData.setMatrixCol(new ArrayList<>());
                        } else {
                            chapterData.setDataTableContent(new ArrayList<>());
                        }
                        this.setInitFirstColumnWidthInfo(chapterData);
                        if (BinaryUtils.isEmpty(chapterData.getReferencesInfo())) {
                            chapterData.setReferencesInfo(new ReferencesInfo());
                        }
                    }
                    chapterDataVo.setChapterDataList(dataPage.getData());
                }
            }
        }
        return chapterDataVo;
    }

    private void setInitFirstColumnWidthInfo(PlanTemplateChapterData chapterData) {
        if ((!BinaryUtils.isEmpty(chapterData.getDataTableForm()) && (2 == chapterData.getDataTableForm() || 3 == chapterData.getDataTableForm())) &&
                BinaryUtils.isEmpty(chapterData.getFirstColumnWidth())) {
            // 矩阵表格和纵向表格设置初始化首列宽
            chapterData.setFirstColumnWidth(-1);
            chapterData.setFirstColumnWidthValue(120);
        }
    }

    private void ipStringReplacement(ChapterResource resource) {
        Pattern pattern = Pattern.compile("(http|https)://([0-9]{1,3}\\.){3}[0-9]{1,3}");
        String resourcePath = resource.getResourcePath();
        Matcher matcher = pattern.matcher(resourcePath);
        String newPath = matcher.replaceAll("");
        if(newPath.startsWith("/rsm") || newPath.startsWith("rsm")){
            newPath = newPath.replace("/rsm","").replace("rsm","");
        }
        resource.setResourcePath(httpPath+newPath);

    }

    @Override
    public boolean deletePlanTemplateChapter(PlanTemplateChapter templateChapter) {
        if (templateChapter == null) {
            throw new BusinessException("模板章节参数不能为空!");
        }
        if (templateChapter.getPlanTemplateId() == null && templateChapter.getId() == null) {
            throw new BusinessException("模板章节删除主键不能为空!");
        }
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        if (templateChapter.getPlanTemplateId() != null) {
            queryBuilder.must(QueryBuilders.termQuery("planTemplateId", templateChapter.getPlanTemplateId()));
        }
        if (templateChapter.getId() != null) {
            queryBuilder.must(QueryBuilders.termQuery("id", templateChapter.getId()));
        }
        List<PlanTemplateChapter> chapterList = planTemplateChapterDao.getListByQuery(queryBuilder);
        if (!CollectionUtils.isEmpty(chapterList)) {
            chapterList.forEach(chapter -> {
                chapter.setStatus(0);
                planTemplateChapterDao.saveOrUpdate(chapter);
                // 删除章节数据
                BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
                boolQueryBuilder.must(QueryBuilders.termQuery("planTemplateId", chapter.getPlanTemplateId()));
                boolQueryBuilder.must(QueryBuilders.termQuery("templateChapterId", chapter.getId()));
                planTemplateChapterDataDao.deleteByQuery(boolQueryBuilder, true);
                // 递归删除
                handlerDeleteChapter(chapter.getId());
            });
        }
        return true;
    }

    @Override
    public Long copyPlanTemplateChapter(Long chapterId, String chapterName, SysUser user) {
        if (chapterId == null) {
            throw new BusinessException("复制方案模板章节主键不能为空!");
        }
        PlanTemplateChapter chapter = planTemplateChapterDao.getById(chapterId);
        if (chapter == null) {
            throw new BusinessException("获取方案模板章节错误!");
        }
        String newChapterName = null;
        if (!StringUtils.isEmpty(chapterName)) {
            newChapterName = chapterName;
        } else {
            newChapterName = chapter.getChapterName() + Constants.COPY_CONTENT;
            if (newChapterName.length() > 50) {
                return -1L;
            }
        }
        chapter.setChapterName(newChapterName);
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("planTemplateId", chapter.getPlanTemplateId()));
        queryBuilder.must(QueryBuilders.termQuery("level", chapter.getLevel()));
        queryBuilder.filter(QueryBuilders.rangeQuery("sortNum").gt(chapter.getSortNum()));
        Page<PlanTemplateChapter> page = planTemplateChapterDao.getSortListByQuery(1, 1, queryBuilder, "sortNum", true);
        if (!CollectionUtils.isEmpty(page.getData())) {
            BigDecimal sortNum = (BigDecimal.valueOf(chapter.getSortNum()).add(BigDecimal.valueOf(page.getData().get(0).getSortNum()))).divide(new BigDecimal(2));
            chapter.setSortNum(sortNum.doubleValue());
        } else {
            chapter.setSortNum(BigDecimal.valueOf(chapter.getSortNum()).add(BigDecimal.ONE).doubleValue());
        }
        chapter.setId(null);
        handleUserAndTime(chapter, user);
        List<PlanTemplateIntroduceChapterVo> introduceList = chapter.getPlanTemplateIntroduceChapterVoList();
        if (!CollectionUtils.isEmpty(introduceList)) {
            for (PlanTemplateIntroduceChapterVo introduce: introduceList) {
                introduce.setDelete(1);
            }
            chapter.setPlanTemplateIntroduceChapterVoList(introduceList);
        }
        chapter.setIntroduceButton(1);
        Long id = planTemplateChapterDao.saveOrUpdate(chapter);

        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("planTemplateId", chapter.getPlanTemplateId()));
        query.must(QueryBuilders.termQuery("templateChapterId", chapterId));
        List<PlanTemplateChapterData> chapterDataList = planTemplateChapterDataDao.getListByQuery(query);
        if (!CollectionUtils.isEmpty(chapterDataList)) {
            chapterDataList.forEach(chapterData -> {
                chapterData.setTemplateChapterId(id);
                chapterData.setId(null);
                planTemplateChapterDataDao.saveOrUpdate(chapterData);
            });
        }
        // 递归复制子模板章节
        handlerCopyChapter(chapterId, user, id);
        return id;
    }

    @Override
    public boolean resetSort(ResetSortVo resetSortVo) {
        if (resetSortVo == null) {
            throw new BusinessException("排序参数不能为空!");
        }
        if (resetSortVo.getId() == null) {
            throw new BusinessException("主键不能为空!");
        }
        PlanTemplateChapter chapter = planTemplateChapterDao.getById(resetSortVo.getId());
        if (chapter == null) {
            throw new BusinessException("获取模板章节错误!");
        }
        if (resetSortVo.getTargetId() == null) {
            throw new BusinessException("目标主键不能为空!");
        }
        if (resetSortVo.getSign() == null) {
            throw new BusinessException("位置标识不能为空!");
        }
        if (Objects.equals(resetSortVo.getSign(), 1) || Objects.equals(resetSortVo.getSign(), -1)) {
            PlanTemplateChapter targetChapter = planTemplateChapterDao.getById(resetSortVo.getTargetId());
            resetSortVo.setParentId(targetChapter.getParentId());
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            queryBuilder.must(QueryBuilders.termQuery("parentId", targetChapter.getParentId()));
            queryBuilder.must(QueryBuilders.termQuery("planTemplateId", targetChapter.getPlanTemplateId()));
            queryBuilder.must(QueryBuilders.termQuery("status", 1));
            long count = planTemplateChapterDao.countByCondition(queryBuilder);
            Page<PlanTemplateChapter> chapterPage = planTemplateChapterDao.getSortListByQuery(1, (int) count, queryBuilder, "sortNum", true);
            if (chapterPage == null || CollectionUtils.isEmpty(chapterPage.getData())) {
                resetSortVo.setTargetPosition(BigDecimal.ZERO);
            } else {
                List<Long> templateChapterIds = chapterPage.getData().stream().map(template -> template.getId()).collect(Collectors.toList());
                int targetIndex = templateChapterIds.indexOf(resetSortVo.getTargetId());
                if (templateChapterIds.contains(resetSortVo.getId())) {
                    int initIndex = templateChapterIds.indexOf(resetSortVo.getId());
                    if (Objects.equals(resetSortVo.getSign(), -1)) {
                        if (targetIndex > initIndex) {
                            if (targetIndex - 1 < 0) {
                                resetSortVo.setTargetPosition(BigDecimal.ZERO);
                            } else {
                                resetSortVo.setTargetPosition(new BigDecimal(targetIndex).subtract(BigDecimal.ONE));
                            }
                        } else {
                            resetSortVo.setTargetPosition(new BigDecimal(targetIndex));
                        }
                    } else {
                        if (targetIndex < initIndex) {
                            resetSortVo.setTargetPosition(new BigDecimal(targetIndex).add(BigDecimal.ONE));
                        } else {
                            resetSortVo.setTargetPosition(new BigDecimal(targetIndex));
                        }
                    }
                } else {
                    if (Objects.equals(resetSortVo.getSign(), -1)) {
                        if (targetIndex - 1 < 0) {
                            resetSortVo.setTargetPosition(BigDecimal.ZERO);
                        } else {
                            resetSortVo.setTargetPosition(new BigDecimal(targetIndex));
                        }
                    } else {
                        resetSortVo.setTargetPosition(new BigDecimal(targetIndex).add(BigDecimal.ONE));
                    }
                }
            }
        } else if (Objects.equals(resetSortVo.getSign(), 0)) {
            resetSortVo.setParentId(resetSortVo.getTargetId());
            resetSortVo.setTargetPosition(BigDecimal.ZERO);
        } else {
            throw new BusinessException("位置标识输入错误!");
        }
        chapter.setParentId(resetSortVo.getParentId());
        // 设置序号
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("parentId", resetSortVo.getParentId()));
        queryBuilder.must(QueryBuilders.termQuery("planTemplateId", chapter.getPlanTemplateId()));
        queryBuilder.must(QueryBuilders.termQuery("status", 1));
        long count = planTemplateChapterDao.countByCondition(queryBuilder);
        if (count > 0) {
            Page<PlanTemplateChapter> chapterPage = planTemplateChapterDao.getSortListByQuery(1, (int) count, queryBuilder, "sortNum", true);
            if (CollectionUtils.isEmpty(chapterPage.getData())) {
                throw new BusinessException("获取方案章节列表错误");
            }
            List<PlanTemplateChapter>  templateChapterList = chapterPage.getData();
            PlanTemplateChapter templateChapter = templateChapterList.get(0);
            BigDecimal sortNum = BigDecimal.valueOf(templateChapter.getSortNum()).divide(new BigDecimal(2));
            chapter.setSortNum(sortNum.doubleValue());
        } else {
            chapter.setSortNum(1D);
        }
        // 设置层级
        if (Objects.equals(resetSortVo.getParentId(), 0L)) {
            chapter.setLevel(1);
        } else {
            PlanTemplateChapter parentChapter = planTemplateChapterDao.getById(resetSortVo.getParentId());
            if (parentChapter == null) {
                throw new BusinessException("获取父章节信息错误!");
            }
            chapter.setLevel(parentChapter.getLevel() + 1);
        }
        planTemplateChapterDao.saveOrUpdate(chapter);
        // 设置移动章节的子章节的层级
        BoolQueryBuilder levelBuilder = QueryBuilders.boolQuery();
        levelBuilder.must(QueryBuilders.termQuery("parentId", chapter.getId()));
        levelBuilder.must(QueryBuilders.termQuery("planTemplateId", chapter.getPlanTemplateId()));
        levelBuilder.must(QueryBuilders.termQuery("status", 1));
        List<PlanTemplateChapter> listByQuery = planTemplateChapterDao.getListByQuery(levelBuilder);
        for (PlanTemplateChapter templateChapter : listByQuery) {
            templateChapter.setLevel(chapter.getLevel() + 1);
            // 如果还有子章节设置子章节层级
            BoolQueryBuilder subLevelBuilder = QueryBuilders.boolQuery();
            subLevelBuilder.must(QueryBuilders.termQuery("parentId", templateChapter.getId()));
            subLevelBuilder.must(QueryBuilders.termQuery("planTemplateId", templateChapter.getPlanTemplateId()));
            subLevelBuilder.must(QueryBuilders.termQuery("status", 1));
            List<PlanTemplateChapter> planTemplateChapterList = planTemplateChapterDao.getListByQuery(subLevelBuilder);
            if (!CollectionUtils.isEmpty(planTemplateChapterList)) {
                handlerChapterLevel(templateChapter, planTemplateChapterList);
            }
        }
        planTemplateChapterDao.saveOrUpdateBatch(listByQuery);

        resetSortVo.setInitPosition(BigDecimal.ZERO);
        resetSortVo.setTargetPosition(resetSortVo.getTargetPosition());

        // 重新按顺序查询模板章节列表
        long sortCount = planTemplateChapterDao.countByCondition(queryBuilder);
        Page<PlanTemplateChapter> chapterPage = planTemplateChapterDao.getSortListByQuery(1, (int) sortCount, queryBuilder, "sortNum", true);
        List<PlanTemplateChapter> chapterList = chapterPage.getData();
        if (!CollectionUtils.isEmpty(chapterList)) {
            if (resetSortVo.getInitPosition().compareTo(resetSortVo.getTargetPosition()) > 0) {
                if (resetSortVo.getTargetPosition().subtract(BigDecimal.ONE).compareTo(BigDecimal.ZERO) < 0) {
                    PlanTemplateChapter targetChapter = chapterList.get(resetSortVo.getTargetPosition().intValue());
                    BigDecimal sortNum = BigDecimal.valueOf(targetChapter.getSortNum()).divide(new BigDecimal(2));
                    chapter.setSortNum(sortNum.doubleValue());
                    planTemplateChapterDao.saveOrUpdate(chapter);
                } else {
                    int i = resetSortVo.getTargetPosition().subtract(BigDecimal.ONE).intValue();
                    PlanTemplateChapter targetChapter1 = chapterList.get(i);
                    PlanTemplateChapter targetChapter2 = chapterList.get(resetSortVo.getTargetPosition().intValue());
                    if (targetChapter1 == null || targetChapter2 == null) {
                        throw new BusinessException("获取移动目标章节信息错误!");
                    }
                    BigDecimal sortNum = (BigDecimal.valueOf(targetChapter1.getSortNum()).add(BigDecimal.valueOf(targetChapter2.getSortNum()))).divide(new BigDecimal(2));
                    chapter.setSortNum(sortNum.doubleValue());
                    planTemplateChapterDao.saveOrUpdate(chapter);
                }
            } else if (resetSortVo.getInitPosition().compareTo(resetSortVo.getTargetPosition()) < 0) {
                if (resetSortVo.getTargetPosition().add(BigDecimal.ONE).compareTo(new BigDecimal(chapterList.size() - 1)) > 0) {
                    PlanTemplateChapter targetChapter = chapterList.get(resetSortVo.getTargetPosition().intValue());
                    BigDecimal sortNum = BigDecimal.valueOf(targetChapter.getSortNum()).add(BigDecimal.ONE);
                    chapter.setSortNum(sortNum.doubleValue());
                    planTemplateChapterDao.saveOrUpdate(chapter);
                } else {
                    int i = resetSortVo.getTargetPosition().add(BigDecimal.ONE).intValue();
                    PlanTemplateChapter targetChapter1 = chapterList.get(i);
                    PlanTemplateChapter targetChapter2 = chapterList.get(resetSortVo.getTargetPosition().intValue());
                    if (targetChapter1 == null || targetChapter2 == null) {
                        throw new BusinessException("获取移动目标章节信息错误!");
                    }
                    BigDecimal sortNum = (BigDecimal.valueOf(targetChapter1.getSortNum()).add(BigDecimal.valueOf(targetChapter2.getSortNum()))).divide(new BigDecimal(2));
                    chapter.setSortNum(sortNum.doubleValue());
                    planTemplateChapterDao.saveOrUpdate(chapter);
                }
            }
        }
        return true;
    }

    private void handlerChapterLevel(PlanTemplateChapter parentChapter, List<PlanTemplateChapter> planTemplateChapterList) {
        for (PlanTemplateChapter templateChapter : planTemplateChapterList) {
            templateChapter.setLevel(parentChapter.getLevel() + 1);
            planTemplateChapterDao.saveOrUpdate(templateChapter);
            // 如果还有子章节设置子章节层级
            BoolQueryBuilder subLevelBuilder = QueryBuilders.boolQuery();
            subLevelBuilder.must(QueryBuilders.termQuery("parentId", templateChapter.getId()));
            subLevelBuilder.must(QueryBuilders.termQuery("planTemplateId", templateChapter.getPlanTemplateId()));
            subLevelBuilder.must(QueryBuilders.termQuery("status", 1));
            List<PlanTemplateChapter> parentChapterList = planTemplateChapterDao.getListByQuery(subLevelBuilder);
            if (!CollectionUtils.isEmpty(parentChapterList)) {
                handlerChapterLevel(templateChapter, parentChapterList);
            }
        }
    }

    @Override
    public boolean deletePlanTemplateChapterData(Long id) {
        if (id == null) {
            throw new BusinessException("模板章节数据主键不能为空!");
        }
        if (id == 0) {
            return true;
        }
        planTemplateChapterDataDao.deleteById(id);
        /*PlanTemplateChapterData chapterData = planTemplateChapterDataDao.getById(id);
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("templateChapterId", chapterData.getTemplateChapterId()));
        List<PlanTemplateChapterData> chapterDataList = planTemplateChapterDataDao.getListByQuery(queryBuilder);
        if (!CollectionUtils.isEmpty(chapterDataList)) {
            chapterDataList.forEach(data -> {
                data.setPreviewOrder(0);
                planTemplateChapterDataDao.saveOrUpdate(data);
            });
        }*/
        return true;
    }

    @Override
    public PlanTemplateChapter getRemark(Long chapterId) {
        if (chapterId == null) {
            throw new BusinessException("章节主键不能为空!");
        }
        return planTemplateChapterDao.getById(chapterId);
    }

    @Override
    public PlanTemplateChapterData getTemplateChapterData(Long dataId) {
        if (dataId == null) {
            throw new BusinessException("数据主键不能为空!");
        }
        return planTemplateChapterDataDao.getById(dataId);
    }

    @Override
    public boolean checkViewType(String viewType) {
        if (StringUtils.isEmpty(viewType)) {
            throw new BusinessException("制品类型不能为空!");
        }
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("type", 1));
        queryBuilder.must(QueryBuilders.wildcardQuery("diagramProductType.keyword", "*" + viewType + "*"));
        List<PlanTemplateChapterData> chapterDataList = planTemplateChapterDataDao.getListByQuery(queryBuilder);
        if (CollectionUtils.isEmpty(chapterDataList)) {
            return true;
        }
        return false;
    }

    @Override
    public List<PlanTemplateChapter> findPlanChapterList(Long planTemplateId) {
        if(planTemplateId == null) {
            throw new BusinessException("参数不能为空!");
        }
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("planTemplateId", planTemplateId));
        queryBuilder.must(QueryBuilders.termQuery("status", 1));

        List<SortBuilder<?>> sorts = new ArrayList<>();
        SortBuilder<?> levelSort = SortBuilders.fieldSort("level").order(SortOrder.ASC);
        SortBuilder<?> timeSort = SortBuilders.fieldSort("sortNum").order(SortOrder.ASC);
        sorts.add(levelSort);
        sorts.add(timeSort);
        long count = planTemplateChapterDao.countByCondition(queryBuilder);
        Page<PlanTemplateChapter> templateChapterPage = planTemplateChapterDao.getSortListByQuery(1, (int) count, queryBuilder, sorts);
        if (templateChapterPage != null && !CollectionUtils.isEmpty(templateChapterPage.getData())) {
            return templateChapterPage.getData();
        }
        return Collections.emptyList();
    }

    @Override
    public List<PlanTemplateChapterData> findChapterDataList(Long templateChapterId) {
        if (templateChapterId == null) {
            throw new BusinessException("参数不能为空!");
        }
        PlanTemplateChapter chapter = planTemplateChapterDao.getById(templateChapterId);
        if (chapter == null) {
            throw new BusinessException("获取方案模板章节错误!");
        }
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("planTemplateId", chapter.getPlanTemplateId()));
        queryBuilder.must(QueryBuilders.termQuery("templateChapterId", templateChapterId));
        long count = planTemplateChapterDataDao.countByCondition(queryBuilder);
        Page<PlanTemplateChapterData> chapterDataPage = planTemplateChapterDataDao.getSortListByQuery(1, (int)count, queryBuilder, "configOrder", true);
        if (chapterDataPage != null && !CollectionUtils.isEmpty(chapterDataPage.getData())) {
            return chapterDataPage.getData();
        }
        return Collections.emptyList();
    }

    @Override
    public List<PlanTemplateChapter> findLevelTemplateChapterList(Long planTemplateId, Long templateParentId, Integer level) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("planTemplateId", planTemplateId));
        queryBuilder.must(QueryBuilders.termQuery("parentId", templateParentId));
        queryBuilder.must(QueryBuilders.termQuery("level", level));
        queryBuilder.must(QueryBuilders.termQuery("status", 1));

        List<SortBuilder<?>> sorts = new ArrayList<>();
        SortBuilder<?> levelSort = SortBuilders.fieldSort("level").order(SortOrder.ASC);
        SortBuilder<?> timeSort = SortBuilders.fieldSort("sortNum").order(SortOrder.ASC);
        sorts.add(levelSort);
        sorts.add(timeSort);
        long count = planTemplateChapterDao.countByCondition(queryBuilder);
        Page<PlanTemplateChapter> templateChapterPage = planTemplateChapterDao.getSortListByQuery(1, (int) count, queryBuilder, sorts);
        if (templateChapterPage != null && !CollectionUtils.isEmpty(templateChapterPage.getData())) {
            return templateChapterPage.getData();
        }
        return Collections.emptyList();
    }

    @Override
    public Boolean refreshTemplateData() {
        BoolQueryBuilder diagramQuery = QueryBuilders.boolQuery();
        diagramQuery.must(QueryBuilders.termQuery("type", 1));
        diagramQuery.must(QueryBuilders.termQuery("productControl.keyword", "1"));
        long count = planTemplateChapterDataDao.countByCondition(diagramQuery);
        Page<PlanTemplateChapterData> chapterDataPage = planTemplateChapterDataDao.getSortListByQuery(1, (int)count, diagramQuery, "createTime", false);
        if (chapterDataPage != null && !CollectionUtils.isEmpty(chapterDataPage.getData())) {
            List<PlanTemplateChapterData> data = chapterDataPage.getData();
            for (PlanTemplateChapterData chapterData : data) {
                chapterData.setDiagramProductType("");
            }
            planTemplateChapterDataDao.saveOrUpdateBatch(data);
        }

        BoolQueryBuilder tableQuery = QueryBuilders.boolQuery();
        tableQuery.must(QueryBuilders.termQuery("type", 2));
        tableQuery.must(QueryBuilders.termQuery("explain.keyword", "0"));
        long tableCount = planTemplateChapterDataDao.countByCondition(tableQuery);
        Page<PlanTemplateChapterData> tableChapterDataPage = planTemplateChapterDataDao.getSortListByQuery(1, (int)tableCount, tableQuery, "createTime", false);
        if (tableChapterDataPage != null && !CollectionUtils.isEmpty(tableChapterDataPage.getData())) {
            List<PlanTemplateChapterData> data = tableChapterDataPage.getData();
            for (PlanTemplateChapterData chapterData : data) {
                chapterData.setDataTableRemarkStatus("1");
            }
            planTemplateChapterDataDao.saveOrUpdateBatch(data);
        }
        return true;
    }

    private double handleSortNum(PlanTemplateChapterVo planTemplateChapterVo) {
        if (planTemplateChapterVo.getType() == null) {
            throw new BusinessException("新增章节类型不能为空!");
        }
        if (planTemplateChapterVo.getType() == 1) {
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            queryBuilder.must(QueryBuilders.termQuery("parentId", 0));
            queryBuilder.must(QueryBuilders.termQuery("planTemplateId", planTemplateChapterVo.getPlanTemplateChapter().getPlanTemplateId()));
            queryBuilder.must(QueryBuilders.termQuery("status", 1));
            long count = planTemplateChapterDao.countByCondition(queryBuilder);
            if (count > 0) {
                Page<PlanTemplateChapter> chapterPage = planTemplateChapterDao.getSortListByQuery(1, (int) count, queryBuilder, "sortNum", true);
                if (CollectionUtils.isEmpty(chapterPage.getData())) {
                    throw new BusinessException("获取方案模板章节错误!");
                }
                List<PlanTemplateChapter> chapterList = chapterPage.getData();
                return chapterList.get(chapterList.size() - 1).getSortNum() + 1;
            } else {
                return 1D;
            }
        } else if (planTemplateChapterVo.getType() == 2) {
            if (planTemplateChapterVo.getRelativeId() == null) {
                throw new BusinessException("关联向下插入章节主键错误!");
            }
            PlanTemplateChapter chapter = planTemplateChapterDao.getById(planTemplateChapterVo.getRelativeId());
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            queryBuilder.must(QueryBuilders.termQuery("parentId", planTemplateChapterVo.getPlanTemplateChapter().getParentId()));
            queryBuilder.must(QueryBuilders.termQuery("planTemplateId", planTemplateChapterVo.getPlanTemplateChapter().getPlanTemplateId()));
            queryBuilder.must(QueryBuilders.termQuery("status", 1));
            queryBuilder.filter(QueryBuilders.rangeQuery("sortNum").gt(chapter.getSortNum()));
            long count = planTemplateChapterDao.countByCondition(queryBuilder);
            if (count > 0) {
                Page<PlanTemplateChapter> chapterPage = planTemplateChapterDao.getSortListByQuery(1, (int) count, queryBuilder, "sortNum", true);
                if (CollectionUtils.isEmpty(chapterPage.getData())) {
                    throw new BusinessException("获取方案模板章节错误!");
                }
                List<PlanTemplateChapter> chapterList = chapterPage.getData();
                return (BigDecimal.valueOf(chapterList.get(0).getSortNum()).add(BigDecimal.valueOf(chapter.getSortNum()))).divide(new BigDecimal(2)).doubleValue();
            } else {
                return chapter.getSortNum() + 1;
            }
        } else if (planTemplateChapterVo.getType() == 3) {
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            queryBuilder.must(QueryBuilders.termQuery("parentId", planTemplateChapterVo.getPlanTemplateChapter().getParentId()));
            queryBuilder.must(QueryBuilders.termQuery("planTemplateId", planTemplateChapterVo.getPlanTemplateChapter().getPlanTemplateId()));
            queryBuilder.must(QueryBuilders.termQuery("status", 1));
            long count = planTemplateChapterDao.countByCondition(queryBuilder);
            if (count > 0) {
                Page<PlanTemplateChapter> chapterPage = planTemplateChapterDao.getSortListByQuery(1, (int) count, queryBuilder, "sortNum", true);
                if (CollectionUtils.isEmpty(chapterPage.getData())) {
                    throw new BusinessException("获取方案模板章节错误!");
                }
                List<PlanTemplateChapter> chapterList = chapterPage.getData();
                return chapterList.get(chapterList.size() - 1).getSortNum() + 1;
            } else {
                return 1D;
            }
        }
        return 1D;
    }

    /**
     * 递归获取子章节信息
     * @param childTreeList
     * @param planTemplateId
     */
    private void getChildChapter(List<PlanTemplateChapterTreeVo> childTreeList, Long planTemplateId) {
        if (!CollectionUtils.isEmpty(childTreeList)) {
            childTreeList.forEach(childChapter -> {
                BoolQueryBuilder query = QueryBuilders.boolQuery();
                query.must(QueryBuilders.termQuery("parentId", childChapter.getId()));
                query.must(QueryBuilders.termQuery("planTemplateId", planTemplateId));
                query.must(QueryBuilders.termQuery("status", 1));
                long childCount = planTemplateChapterDao.countByCondition(query);
                if (childCount > 0) {
                    Page<PlanTemplateChapter> childChapterPage = planTemplateChapterDao.getSortListByQuery(1, (int) childCount, query, "sortNum", true);
                    List<PlanTemplateChapter> childData = childChapterPage.getData();
                    if (!CollectionUtils.isEmpty(childData)) {
                        List<PlanTemplateChapterTreeVo> treeList = new ArrayList<>();
                        for (int i = 0; i < childData.size(); i++) {
                            PlanTemplateChapterTreeVo childTree = new PlanTemplateChapterTreeVo();
                            BeanUtils.copyProperties(childData.get(i), childTree);
                            StringBuilder sb = new StringBuilder();
                            sb.append(childChapter.getSerialNum()).append(".").append(i + 1);
                            childTree.setSerialNum(sb.toString());
                            childTree.setFullName(sb.toString() + " " + childTree.getChapterName());
                            childTree.setRequired(Objects.equals(childData.get(i).getRequired(), "1"));
                            treeList.add(childTree);
                            childChapter.setChild(treeList);
                        }
                        if (!CollectionUtils.isEmpty(treeList)) {
                            getChildChapter(treeList, planTemplateId);
                        }
                    }
                }
            });
        }
    }

    /**
     * 递归删除
     * @param parentId
     */
    private void handlerDeleteChapter(Long parentId) {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        queryBuilder.must(QueryBuilders.termQuery("parentId", parentId));
        List<PlanTemplateChapter> chapterList = planTemplateChapterDao.getListByQuery(queryBuilder);
        chapterList.forEach(chapter -> {
            chapter.setStatus(0);
            planTemplateChapterDao.saveOrUpdate(chapter);
            // 删除章节数据
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            boolQueryBuilder.must(QueryBuilders.termQuery("planTemplateId", chapter.getPlanTemplateId()));
            boolQueryBuilder.must(QueryBuilders.termQuery("templateChapterId", chapter.getId()));
            planTemplateChapterDataDao.deleteByQuery(boolQueryBuilder, true);
            handlerDeleteChapter(chapter.getId());
        });
    }

    /**
     * 递归复制子模板章节
     * @param parentId
     * @param user
     */
    private void handlerCopyChapter(Long parentId, SysUser user, Long newId) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("parentId", parentId));
        List<PlanTemplateChapter> chapterList = planTemplateChapterDao.getListByQuery(query);
        if (!CollectionUtils.isEmpty(chapterList)) {
            chapterList.forEach(chapter -> {
                /*BoolQueryBuilder builder = QueryBuilders.boolQuery();
                builder.must(QueryBuilders.termQuery("planTemplateId", chapter.getPlanTemplateId()));
                builder.must(QueryBuilders.termQuery("level", chapter.getLevel()));
                builder.filter(QueryBuilders.rangeQuery("sortNum").gt(newChapter.getSortNum()));
                Page<PlanTemplateChapter> page = planTemplateChapterDao.getSortListByQuery(1, 1, builder, "sortNum", true);
                if (!CollectionUtils.isEmpty(page.getData())) {
                    BigDecimal sortNum = (new BigDecimal(chapter.getSortNum()).add(new BigDecimal(page.getData().get(0).getSortNum()))).divide(new BigDecimal(2));
                    chapter.setSortNum(sortNum.doubleValue());
                } else {
                    chapter.setSortNum(new BigDecimal(chapter.getSortNum()).add(BigDecimal.ONE).doubleValue());
                }*/
                PlanTemplateChapter newChapter = new PlanTemplateChapter();
                BeanUtils.copyProperties(chapter, newChapter);
                newChapter.setId(null);
                newChapter.setParentId(newId);
                handleUserAndTime(newChapter, user);
                List<PlanTemplateIntroduceChapterVo> introduceList = chapter.getPlanTemplateIntroduceChapterVoList();
                if (!CollectionUtils.isEmpty(introduceList)) {
                    for (PlanTemplateIntroduceChapterVo introduce: introduceList) {
                        introduce.setDelete(1);
                    }
                    newChapter.setPlanTemplateIntroduceChapterVoList(introduceList);
                }
                newChapter.setIntroduceButton(1);
                Long id = planTemplateChapterDao.saveOrUpdate(newChapter);
                BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
                queryBuilder.must(QueryBuilders.termQuery("planTemplateId", chapter.getPlanTemplateId()));
                queryBuilder.must(QueryBuilders.termQuery("templateChapterId", chapter.getId()));
                List<PlanTemplateChapterData> chapterDataList = planTemplateChapterDataDao.getListByQuery(queryBuilder);
                if (!CollectionUtils.isEmpty(chapterDataList)) {
                    chapterDataList.forEach(chapterData -> {
                        chapterData.setTemplateChapterId(id);
                        chapterData.setId(null);
                        planTemplateChapterDataDao.saveOrUpdate(chapterData);
                    });
                }
                handlerCopyChapter(chapter.getId(), user, id);
            });
        }
    }

    private void handleUserAndTime(PlanTemplateChapter planTemplateChapter, SysUser user) {
        if (user != null) {
            planTemplateChapter.setModifyTime(ESUtil.getNumberDateTime());
            planTemplateChapter.setModifierCode(user.getLoginCode());
            planTemplateChapter.setModifierName(user.getLoginCode());
            if (planTemplateChapter.getId() == null) {
                planTemplateChapter.setCreateTime(ESUtil.getNumberDateTime());
                planTemplateChapter.setCreatorCode(user.getLoginCode());
                planTemplateChapter.setCreatorName(user.getLoginCode());
            }
        }
    }

    /**
     *  校验模板基本信息完整性
     * @param planTemplateChapterVo
     */
    private void checkPlanTemplateChapter(PlanTemplateChapterVo planTemplateChapterVo) {
        if (planTemplateChapterVo == null) {
            throw new BusinessException("方案模板章节参数不能为空!");
        }
        PlanTemplateChapter planTemplateChapter = planTemplateChapterVo.getPlanTemplateChapter();
        if (planTemplateChapter == null) {
            throw new BusinessException("方案模板章节基本信息参数不能为空!");
        }
        if (StringUtils.isEmpty(planTemplateChapter.getChapterName().trim())) {
            throw new BusinessException("章节名称不能为空!");
        }
        if (planTemplateChapter.getChapterName().trim().length() <= 0 ||
                planTemplateChapter.getChapterName().trim().length() > 50) {
            throw new BusinessException("章节名称最多50个字符!");
        }
        if (planTemplateChapter.getRequired() == null) {
            throw new BusinessException("方案模板章节基本信息必填不能为空!");
        }
        if (planTemplateChapter.getUserAddContent() == null) {
            throw new BusinessException("方案模板章节用户自行添加内容快不能为空!");
        }
        if (planTemplateChapter.getLevel() == null) {
            throw new BusinessException("方案模板章节层级不能为空!");
        }
        if (planTemplateChapter.getParentId() == null) {
            throw new BusinessException("父层级主键不能为空!");
        }
        if (planTemplateChapter.getPlanTemplateId() == null) {
            throw new BusinessException("方案模板主键不能为空!");
        }
        if (!StringUtils.isEmpty(planTemplateChapter.getChapterDesc()) &&
                planTemplateChapter.getChapterDesc().trim().length() > 1000) {
            throw new BusinessException("章节说明最多1000个字符!");
        }
        if (planTemplateChapter.getLevel() > 8) {
            throw new BusinessException("已超过最大层级!");
        }
    }

    private void checkChapterData(PlanTemplateChapterData chapterData) {
        if (chapterData.getType() == 1) {
            if (StringUtils.isEmpty(chapterData.getProductRequired())) {
                throw new BusinessException("制品是否必填不能为空!");
            }
            /*if (StringUtils.isEmpty(chapterData.getProductControl())) {
                throw new BusinessException("限定视图类型不能为空!");
            }
            if (Objects.equals("0", chapterData.getProductControl())
                    && StringUtils.isEmpty(chapterData.getDiagramProductType())) {
                throw new BusinessException("视图制品类型不能为空!");
            }*/
        } else if (chapterData.getType() == 2) {
            if (chapterData.getDataTableForm() == null) {
                throw new BusinessException("表格形式不能为空!");
            }
            if (StringUtils.isEmpty(chapterData.getDataTableRequired())) {
                throw new BusinessException("表格是否必填不能为空!");
            }
            if (StringUtils.isEmpty(chapterData.getUserAddRow())) {
                throw new BusinessException("表格可添加多行不能为空!");
            }
            if (StringUtils.isEmpty(chapterData.getConfigSerial())) {
                throw new BusinessException("表格是否配置序号不能为空!");
            }
            /*if (StringUtils.isEmpty(chapterData.getExplain())) {
                throw new BusinessException("表格说明不能为空!");
            }*/
            if (StringUtils.isEmpty(chapterData.getDataTableRemarkStatus())) {
                throw new BusinessException("表格可编辑说明不能为空!");
            }
            if (Objects.equals(chapterData.getDataTableForm(), 1) || Objects.equals(chapterData.getDataTableForm(), 2)) {
                List<RowTableContentVo> dataTableContent = chapterData.getDataTableContent();
                if (CollectionUtils.isEmpty(dataTableContent)) {
                    throw new BusinessException("表格内容不能为空!");
                }
                dataTableContent.forEach(content -> {
                    if (StringUtils.isEmpty(content.getName())){
                        throw new BusinessException("表格属性名称不能为空!");
                    }
                    if (content.getType() == null){
                        throw new BusinessException("表格属性类型不能为空!");
                    }
                    if ((Objects.equals(TableContentTypeEnum.ASSET.getType(), content.getType()) || Objects.equals(TableContentTypeEnum.BIND_ASSET.getType(), content.getType()))
                            && (content.getCopyConstraint() == null || StringUtils.isEmpty(String.valueOf(content.getCopyConstraint())))){
                        throw new BusinessException("表格限制不能为空!");
                    }
                    if ((Objects.equals(TableContentTypeEnum.STRING.getType(), content.getType()) || Objects.equals(TableContentTypeEnum.TEXT.getType(), content.getType())
                            || Objects.equals(TableContentTypeEnum.ARTICLE.getType(), content.getType()) || Objects.equals(TableContentTypeEnum.ENUM.getType(), content.getType())
                            || Objects.equals(TableContentTypeEnum.ASSET.getType(), content.getType()) || Objects.equals(TableContentTypeEnum.BIND_ASSET.getType(), content.getType()))
                            && (content.getCopyConstraint() == null || StringUtils.isEmpty(content.getCopyConstraint()))) {
                        throw new BusinessException("表格限制不能为空!");
                    }
                });
            } else if (Objects.equals(chapterData.getDataTableForm(), 3)) {
                if (chapterData.getMatrixConfig() == null) {
                    throw new BusinessException("矩阵表格配置不能为空!");
                }
                if (!Objects.equals(chapterData.getMatrixConfig(), 1) && !Objects.equals(chapterData.getMatrixConfig(), 2)) {
                    throw new BusinessException("矩阵表格配置传参错误!");
                }
                List<RowTableContentVo> matrixRowContent = chapterData.getMatrixRow();
                List<RowTableContentVo> matrixColContent = chapterData.getMatrixCol();
                if (CollectionUtils.isEmpty(matrixRowContent) || CollectionUtils.isEmpty(matrixColContent)) {
                    throw new BusinessException("矩阵表格内容不能为空!");
                }
                if (Objects.equals(chapterData.getMatrixConfig(), 1)) {
                    matrixRowContent.forEach(content -> {
                        if (StringUtils.isEmpty(content.getName())){
                            throw new BusinessException("矩阵表格行配置名称不能为空!");
                        }
                        if (content.getType() == null){
                            throw new BusinessException("矩阵表格行配置类型不能为空!");
                        }
                        if ((Objects.equals(TableContentTypeEnum.STRING.getType(), content.getType()) || Objects.equals(TableContentTypeEnum.TEXT.getType(), content.getType())
                                || Objects.equals(TableContentTypeEnum.ARTICLE.getType(), content.getType()) || Objects.equals(TableContentTypeEnum.ENUM.getType(), content.getType()))
                                && (content.getCopyConstraint() == null || StringUtils.isEmpty(content.getCopyConstraint()))) {
                            throw new BusinessException("矩阵表格行配置限制不能为空!");
                        }
                    });
                    matrixColContent.forEach(content -> {
                        if (StringUtils.isEmpty(content.getName())){
                            throw new BusinessException("矩阵表格列配置名称不能为空!");
                        }
                    });
                } else {
                    matrixColContent.forEach(content -> {
                        if (StringUtils.isEmpty(content.getName())){
                            throw new BusinessException("矩阵表格列配置名称不能为空!");
                        }
                        if (content.getType() == null){
                            throw new BusinessException("矩阵表格列配置类型不能为空!");
                        }
                        if ((Objects.equals(TableContentTypeEnum.STRING.getType(), content.getType()) || Objects.equals(TableContentTypeEnum.TEXT.getType(), content.getType())
                                || Objects.equals(TableContentTypeEnum.ARTICLE.getType(), content.getType()) || Objects.equals(TableContentTypeEnum.ENUM.getType(), content.getType()))
                                && (content.getCopyConstraint() == null || StringUtils.isEmpty(content.getCopyConstraint()))) {
                            throw new BusinessException("矩阵表格列配置限制不能为空!");
                        }
                    });
                    matrixRowContent.forEach(content -> {
                        if (StringUtils.isEmpty(content.getName())){
                            throw new BusinessException("矩阵表格行配置名称不能为空!");
                        }
                    });
                }
            } else {
                throw new BusinessException("请选择表格类型!");
            }
        } else if (chapterData.getType() == 3) {
            if (StringUtils.isEmpty(chapterData.getRichTextRequired())) {
                throw new BusinessException("富文本是否必填不能为空!");
            }
        } else if (chapterData.getType() == 4) {
            if (chapterData.getDataSetId() == null) {
                throw new BusinessException("清单制品类型不能为空!");
            }
        }
    }

}
